package main

import (
	"net/http"
	"github.com/labstack/echo"
	"github.com/labstack/echo/middleware"
	"github.com/dgrijalva/jwt-go"
	"time"
)

type User struct {
	Name  string `json:"name" xml:"name" form:"name" query:"name"`
	Email string `json:"email" xml:"email" form:"email" query:"email"`
}

/**
 * @api post /login 用户登录，获取token
 * @apiGroup users
 * @apiParam name     string 用户名称
 * @apiParam password string 密码
 * @apiSuccess 200 json ok
 * @apiExample
 * {"id":1, "name": "n1"}
 */
func login(c echo.Context) error {
	username := c.FormValue("username")
	password := c.FormValue("password")

	if username == "jon" && password == "shhh!" {
		token := jwt.New(jwt.SigningMethodHS256)

		claims := token.Claims.(jwt.MapClaims)
		claims["name"] = "John Snow"
		claims["admin"] = true
		claims["exp"] = time.Now().Add(time.Hour * 72).Unix()

		t, err := token.SignedString([]byte("secret"))
		if err != nil {
			return err
		}
		return c.JSON(http.StatusOK, map[string]string{
			"token": t,
		})
	}

	return echo.ErrUnauthorized
}

func accessible(c echo.Context) error {
	return c.String(http.StatusOK, "Accessible")
}

func restricted(c echo.Context) error {
	user := c.Get("user").(*jwt.Token)
	claims := user.Claims.(jwt.MapClaims)
	name := claims["name"].(string)
	return c.String(http.StatusOK, "Welcome "+name+"!")
}

func isLogin(next echo.HandlerFunc) echo.HandlerFunc {

	j := middleware.JWT([]byte("secret"))

	return func(c echo.Context) error {

		if err := j(next)(c); err != nil {
			return err
		} else {
			user := c.Get("user").(*jwt.Token)
			claims := user.Claims.(jwt.MapClaims)
			exp := claims["exp"].(int64)
			if  time.Now().Unix() > exp{
				return  echo.NewHTTPError(http.StatusUnauthorized, "the token has expired")
			}
		}
		return nil
	}
}

/**
 * @apidoc title of doc
 * @apiVersion 2.0
 * @apiBaseURL https://api.caixw.io
 * @apiLicense MIT https://opensource.org/licenses/MIT
 * @apiContent
 * <p>这里可以是html</p>
 * <p>会被原样输出</p>
 */
func main() {
	e := echo.New()

	// Middleware
	e.Use(middleware.Logger())
	e.Use(middleware.Recover())
	e.Use(isLogin)

	// Login route
	e.POST("/login", login)

	// Unauthenticated route
	e.GET("/", accessible)

	// Restricted group
	r := e.Group("/restricted")
	//r.Use(middleware.JWT([]byte("secret")))
	r.GET("", restricted)

	e.Logger.Fatal(e.Start(":1323"))
}
